package com.internetCafes.spms.web.sys.service.impl;

import com.internetCafes.spms.common.CommonConstants;
import com.internetCafes.spms.common.utils.ShiroUtils;
import com.internetCafes.spms.common.utils.StringUtils;
import com.internetCafes.spms.core.exception.RRException;
import com.internetCafes.spms.core.model.pageModel.DataGrid;
import com.internetCafes.spms.core.utils.IdWorker;
import com.internetCafes.spms.web.certificate.service.CertificateInfoService;
import com.internetCafes.spms.web.sys.entity.dto.profession.CertificateProfessionalSaveDTO;
import com.internetCafes.spms.web.sys.entity.dto.profession.CertificateProfessionalUpdateDTO;
import com.internetCafes.spms.web.sys.entity.vo.profession.CertificateProfessionalPageVO;
import com.internetCafes.spms.web.sys.entity.vo.profession.ProfessionalsOrCategoriesVO;
import com.internetCafes.spms.web.sys.model.ConfInfo;
import com.internetCafes.spms.web.sys.model.UserInfo;
import com.internetCafes.spms.web.sys.service.CertificateProfessionalService;
import com.internetCafes.spms.web.sys.service.ConfInfoService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.format.ResolverStyle;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CertificateProfessionalServiceImpl implements CertificateProfessionalService {

    @Autowired
    private ConfInfoService confInfoService;

    @Autowired
    private CertificateInfoService certificateInfoService;


    /**
     * 证书专业删除
     *
     * @param confId 专业证书id
     * @author Zj
     */
    @Override
    public void delete(Long confId) {
        ConfInfo confInfo = confInfoService.findById(confId);
        if (confInfo == null) {
            throw new RRException("记录不存在");
        }
        // 2-判断
        // 2.1-如果是修改专业
        HashMap<String, Object> params;
        if (CommonConstants.ProfessionModuleTag.PROFESSION.getModuleTag().equals(confInfo.getModuleTag())) {
            params = new HashMap<>();
            params.put("idType", confInfo.getType());
            params.put("profession", confInfo.getName());
            long certificateCount = certificateInfoService.count(params);
            if (certificateCount != 0L) {
                throw new RRException("专业下有证书，不能删除");
            }
        }
        if (CommonConstants.ProfessionModuleTag.CATEGORY.getModuleTag().equals(confInfo.getModuleTag())) {
            params = new HashMap<>();
            params.put("idType", confInfo.getName());
            long certificateCount = certificateInfoService.count(params);
            if (certificateCount != 0L) {
                throw new RRException("类别下有证书，不能删除");
            }
            params = new HashMap<>();
            params.put("type", confInfo.getName());
            params.put("moduleTag", CommonConstants.CONF_Certificate_Type);
            long confCount = confInfoService.count(params);
            if (confCount != 0l) {
                throw new RRException("类别下有专业，不能删除");
            }
        }
        confInfoService.delete(confId);
    }

    /**
     * 证书专业更新
     *
     * @param dto
     */
    @Override
    public void update(CertificateProfessionalUpdateDTO dto) {
        // 1-判断证书是否支持修改
        if (dto.getId() == null) {
            throw new RRException("参数错误");
        }
        ConfInfo confInfo = confInfoService.findById(dto.getId());
        if (confInfo == null) {
            throw new RRException("记录不存在");
        }
        // 2-判断
        // 2.1-如果是修改专业
        HashMap<String, Object> params;
        if (CommonConstants.ProfessionModuleTag.PROFESSION.getModuleTag().equals(confInfo.getModuleTag())) {
            params = new HashMap<>();
            params.put("idType", confInfo.getType());
            params.put("profession", confInfo.getName());
            long certificateCount = certificateInfoService.count(params);
            if (certificateCount != 0L) {
                throw new RRException("专业下有证书，不能修改");
            }
            // 统一类别不允许同一个专业
            params = new HashMap<>();
            params.put("type", dto.getType());
            params.put("nameEquals", dto.getName());
            params.put("moduleTagEquals", CommonConstants.ProfessionModuleTag.PROFESSION.getModuleTag());
            List<ConfInfo> confirm = confInfoService.query(params);
            if (CollectionUtils.isNotEmpty(confirm) && !confirm.get(0).getId().equals(dto.getId())) {
                throw new RRException("证书专业名称重复");
            }
        }
        if (CommonConstants.ProfessionModuleTag.CATEGORY.getModuleTag().equals(confInfo.getModuleTag())) {
            params = new HashMap<>();
            params.put("idType", confInfo.getName());
            long certificateCount = certificateInfoService.count(params);
            if (certificateCount != 0L) {
                throw new RRException("类别下有证书，不能修改");
            }
            params = new HashMap<>();
            params.put("type", confInfo.getName());
            params.put("moduleTag", CommonConstants.CONF_Certificate_Type);
            long confCount = confInfoService.count(params);
            if (confCount != 0l) {
                throw new RRException("类别下有专业，不能修改");
            }
            // 如果新增专业类别 需要保持专业类别的唯一字段
            params = new HashMap<>();
            params.put("nameEquals", dto.getName());
            params.put("moduleTagEquals", CommonConstants.ProfessionModuleTag.CATEGORY.getModuleTag());
            List<ConfInfo> confirm = confInfoService.query(params);
            if (CollectionUtils.isNotEmpty(confirm) && !confirm.get(0).getId().equals(dto.getId())) {
                throw new RRException("证书类别名称重复");
            }
        }
        ConfInfo confUpdateDO = new ConfInfo();
        BeanUtils.copyProperties(dto, confUpdateDO);
        confUpdateDO.setValue(dto.getName());
        confInfoService.update(confUpdateDO);
    }

    /**
     * 获取证书对应code的类别
     *
     * @param code code编码
     * @return 类别列表
     * @author Zj
     */
    @Override
    public List<ProfessionalsOrCategoriesVO> categories(String code) {
        if (StringUtils.isEmpty(code)) {
            throw new RRException("参数错误！");
        }
        Map params = new HashMap<>();
        params.put("type", code);
        params.put("status", CommonConstants.CommonStatus.ENABLE);
        List<ConfInfo> confTypes = confInfoService.query(params);
        List<ProfessionalsOrCategoriesVO> results = confTypes.stream()
                .map(conf -> new ProfessionalsOrCategoriesVO(conf.getType(), conf.getCode(), conf.getName()))
                .collect(Collectors.toList());
        return results;
    }

    /**
     * 获取证书所有分类
     *
     * @return 分类列表
     * @author Zj
     */
    @Override
    public List<ProfessionalsOrCategoriesVO> types() {
        Map params = new HashMap<>();
        params.put("type", CommonConstants.CONF_Certificate_Type);
        params.put("status", CommonConstants.CommonStatus.ENABLE);
        List<ConfInfo> confTypes = confInfoService.query(params);
        List<ProfessionalsOrCategoriesVO> results = confTypes.stream()
                .map(conf -> new ProfessionalsOrCategoriesVO(conf.getType(), conf.getCode(), conf.getName()))
                .collect(Collectors.toList());
        return results;
    }

    /**
     * 专业证书新增
     *
     * @param dto 新增参数
     * @author Zj
     */
    @Override
    public void save(CertificateProfessionalSaveDTO dto) {
        //**code需要自动生成
        UserInfo user = ShiroUtils.getUserEntity();
        ConfInfo confInfoSaveDO = new ConfInfo();
        BeanUtils.copyProperties(dto, confInfoSaveDO);
        confInfoSaveDO.setCreateBy(user.getId());
        confInfoSaveDO.setCreateTime(new Date());
        confInfoSaveDO.setValue(dto.getName());
        IdWorker id = new IdWorker(2);
        String codeSuffix = id.nextId() + "";
        confInfoSaveDO.setCode(codeSuffix);
        if (CommonConstants.ProfessionModuleTag.CATEGORY.getSaveTag().equals(dto.getSaveTag())) {
            confInfoSaveDO.setModuleTag(CommonConstants.ProfessionModuleTag.CATEGORY.getModuleTag());
            // 如果新增专业类别 需要保持专业类别的唯一字段
            Map<String, Object> params = new HashMap<>();
            params.put("nameEquals", dto.getName());
            params.put("moduleTagEquals", CommonConstants.ProfessionModuleTag.CATEGORY.getModuleTag());
            List<ConfInfo> confirm = confInfoService.query(params);
            if (CollectionUtils.isNotEmpty(confirm)) {
                throw new RRException("证书类别名称重复");
            }
        } else {

            // 统一类别不允许同一个专业
            Map<String, Object> params = new HashMap<>();
            params.put("type", dto.getType());
            params.put("nameEquals", dto.getName());
            params.put("moduleTagEquals", CommonConstants.ProfessionModuleTag.PROFESSION.getModuleTag());
            List<ConfInfo> confirm = confInfoService.query(params);
            if (CollectionUtils.isNotEmpty(confirm)) {
                throw new RRException("证书专业名称重复");
            }
            confInfoSaveDO.setModuleTag(CommonConstants.ProfessionModuleTag.PROFESSION.getModuleTag());
        }
        confInfoService.save(confInfoSaveDO);
    }

    /**
     * 分页获取专业数据
     *
     * @param params   检索参数
     * @param pageNo   当前页
     * @param pageSize 页码大小
     * @return 专业数据分页信息
     * @author Zj
     */
    @Override
    public DataGrid dataGrid(Map<String, Object> params, int pageNo, int pageSize) {

        // 1-首先获取分页数据
        List<ConfInfo> confInfoList = confInfoService.pageByIdDesc(params, (pageNo - 1 < 0 ? -1 : pageNo - 1) * pageSize, pageSize);
        long count = confInfoService.count(params);

        List<CertificateProfessionalPageVO> resultData = new ArrayList<>();
        // 2-获取数据库中大类列表数据
        params = new HashMap<>();
        params.put("type", CommonConstants.CONF_Certificate_Type);
        params.put("status", CommonConstants.CommonStatus.ENABLE);
        List<ConfInfo> confTypes = confInfoService.query(params);

        // 3-获取分类的code列表
        Map<String, String> typeCodeAndName = confTypes.stream()
                .collect(Collectors.toMap(ConfInfo::getCode, ConfInfo::getName));

        // 4-解析出类别列表 如果是类别 仅需要填充证书类型 证书类别即为名称
        List<CertificateProfessionalPageVO> categories = confInfoList.stream()
                .filter(confInfo -> CommonConstants.CONF_CERTIFICATE_TYPE_CATEGORY.equals(confInfo.getModuleTag()))
                .map(confInfo -> {
                    CertificateProfessionalPageVO result = new CertificateProfessionalPageVO();
                    BeanUtils.copyProperties(confInfo, result);
                    result.setTypeName(typeCodeAndName.get(confInfo.getType()));
                    result.setCategoryName(confInfo.getName());
                    result.setTypeCode(confInfo.getType());
                    result.setCategoryCode(confInfo.getCode());
                    return result;
                })
                .collect(Collectors.toList());
        resultData.addAll(categories);
        // 5-解析出专业列表
        List<ConfInfo> professions = confInfoList.stream()
                .filter(confInfo -> CommonConstants.CONF_CERTIFICATE_TYPE_PROFESSIONAL.equals(confInfo.getModuleTag()))
                .collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(professions)) {
            // 6-获取专业列表
            List<String> categoryNames = professions.stream()
                    .map(ConfInfo::getType)
                    .collect(Collectors.toList());
            params = new HashMap<>();
            params.put("names", categoryNames);
            params.put("moduleTag", CommonConstants.CONF_Certificate_Type);
            List<ConfInfo> confCategories = confInfoService.query(params);
            Map<String, String> categoriesNameAndType = confCategories.stream()
                    .collect(Collectors.toMap(ConfInfo::getName, ConfInfo::getType));

            // 7-专业列表遍历
            List<CertificateProfessionalPageVO> professionResults = professions.stream()
                    .map(profession -> {
                        CertificateProfessionalPageVO result = new CertificateProfessionalPageVO();
                        BeanUtils.copyProperties(profession, result);
                        result.setCategoryName(profession.getType());
                        result.setProfessionalName(profession.getName());
                        result.setTypeName(typeCodeAndName.get(categoriesNameAndType.get(profession.getType())));
                        result.setTypeCode(categoriesNameAndType.get(profession.getType()));
                        result.setCategoryCode(profession.getType());
                        return result;
                    })
                    .collect(Collectors.toList());
            resultData.addAll(professionResults);
        }
        List<CertificateProfessionalPageVO> results = resultData.stream()
                .sorted(Comparator.comparing(CertificateProfessionalPageVO::getId).reversed())
                .collect(Collectors.toList());
        // 8-封装分页信息
        return new DataGrid(results, count, pageSize, pageNo);
    }
}
